﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using LowLevelGraphics.Types.Interval;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// RGB Color Filter, filters all colors not in range
    /// R, G, B
    /// </summary>
    public class RGBFilter : BaseForeBackgroundColorFilter
    {
        protected IntInterval m_RInterval = new IntInterval(0, 100);
        protected IntInterval m_GInterval = new IntInterval(0, 10);
        protected IntInterval m_BInterval = new IntInterval(0, 10);
        protected float m_fMinIntensity = -1;
        protected float m_fMinHue = -1;

        protected Colorable m_Colorable = Colorable.None;

        /// <summary>
        /// Initializes a new instance of the <see cref="RGBFilter"/> class.
        /// </summary>
        public RGBFilter()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_colorable"></param>
        public RGBFilter(Colorable _colorable)
        {
            InitializeColorabled(_colorable);
        }

        /// <summary>
        /// Gets or sets colorable
        /// </summary>
        public Colorable Colorable
        {
            get { return m_Colorable; }
            set 
            {
                m_Colorable = value;
                InitializeColorabled(value);
            }
        }

        /// <summary>
        /// Initialize Colorable
        /// </summary>
        /// <param name="_colorable"></param>
        private void InitializeColorabled(Colorable _colorable)
        {
            //for blackinterval we don't need to do anything now, 'cause it's also correctly initialized
            m_RInterval = new IntInterval(0, 0);
            m_GInterval = new IntInterval(0, 0);
            m_BInterval = new IntInterval(0, 0);

            if (_colorable == Colorable.Blue)
            {
                m_BInterval = new IntInterval(0, 0);
            }
            else if (_colorable == Colorable.Green)
            {
                m_GInterval = new IntInterval(0, 255);
            }
            else if (_colorable == Colorable.Magenta)
            {
            }
            else if (_colorable == Colorable.Red)
            {
                m_RInterval = new IntInterval(0, 255);
            }
            else if (_colorable == Colorable.Cyan)
            {
                m_BInterval = new IntInterval(0, 0);
                m_GInterval = new IntInterval(0, 255);
            }
            else if (_colorable == Colorable.White)
            {
                m_RInterval = new IntInterval(255, 255);
                m_GInterval = new IntInterval(255, 255);
                m_BInterval = new IntInterval(255, 255);
            }
            else if (_colorable == Colorable.Yellow)
            {
                m_RInterval = new IntInterval(255, 255);
                m_GInterval = new IntInterval(255, 255);
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RGBFilter"/> class.
        /// </summary>
        /// <param name="_rgbFilter">The _RGB filter.</param>
        internal RGBFilter(RGBFilter _rgbFilter)
        {
            this.m_RInterval = _rgbFilter.m_RInterval;
            this.m_GInterval = _rgbFilter.m_GInterval;
            this.m_BInterval = _rgbFilter.m_BInterval;
            this.m_fMinIntensity = _rgbFilter.m_fMinIntensity;
            this.m_fMinHue = _rgbFilter.m_fMinHue;
        }

        /// <summary>
        /// Gets or sets the R.
        /// </summary>
        /// <value>The R.</value>
        public IntInterval R
        {
            get { return m_RInterval; }
            set { m_RInterval = value; }
        }

        /// <summary>
        /// Gets or sets the G.
        /// </summary>
        /// <value>The G.</value>
        public IntInterval G
        {
            get { return m_GInterval; }
            set { m_GInterval = value; }
        }

        /// <summary>
        /// Gets or sets MinIntensity
        /// </summary>
        public float MinIntensity
        {
            get { return m_fMinIntensity; }
            set { m_fMinIntensity = value; }
        }

        /// <summary>
        /// Gets or sets MinHue
        /// </summary>
        public float MinHue
        {
            get { return m_fMinHue; }
            set { m_fMinHue = value; }
        }

        /// <summary>
        /// Gets or sets the B.
        /// </summary>
        /// <value>The B.</value>
        public IntInterval B
        {
            get { return m_BInterval; }
            set { m_BInterval = value; }
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;

            Color color = Color.Transparent;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            int y = 0;
            int x = 0;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = bitmap.GetPixel(x, y);

                    if (((m_RInterval.Contains(color.R)
                        && m_GInterval.Contains(color.G)
                        && m_BInterval.Contains(color.B)))
                        || 
                        (color.R > m_RInterval.Min && color.G > m_GInterval.Min && color.B > m_BInterval.Min && color.GetHue() > m_fMinHue && color.GetBrightness() > m_fMinIntensity && m_fMinHue>-1 && m_fMinIntensity>-1))
                    {
                        bitmap.SetPixel(x, y, color);
                    }
                    else
                    {
                        bitmap.SetPixel(x, y, m_ColorBackground);
                    }
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new RGBFilter(this);
        }
    }
}
